import { Injectable } from '@nestjs/common';
import * as puppeteer from 'puppeteer';
import { NovelInfo, ChapterInfo } from '../interfaces/crawler.interface';

@Injectable()
export class QidianCrawlerV4 {
  private browser: puppeteer.Browser | null = null;

  async initBrowser(): Promise<void> {
    if (!this.browser) {
      this.browser = await puppeteer.launch({
        headless: true,
        args: [
          '--no-sandbox',
          '--disable-setuid-sandbox',
          '--disable-dev-shm-usage',
          '--disable-gpu',
          '--remote-debugging-port=9222',
        ],
      });
    }
  }

  async closeBrowser(): Promise<void> {
    if (this.browser) {
      await this.browser.close();
      this.browser = null;
    }
  }

  /**
   * 获取小说信息 - 使用用户提供的精确CSS选择器
   */
  async getNovelInfo(url: string): Promise<NovelInfo> {
    await this.initBrowser();
    const page = await this.browser!.newPage();

    try {
      // 设置用户代理和反爬虫措施
      await page.setUserAgent(
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
      );

      await page.evaluateOnNewDocument(() => {
        Object.defineProperty(navigator, 'webdriver', {
          get: () => undefined,
        });
        Object.defineProperty(navigator, 'plugins', {
          get: () => [1, 2, 3, 4, 5],
        });
        Object.defineProperty(navigator, 'languages', {
          get: () => ['zh-CN', 'zh', 'en'],
        });
      });

      await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000 });
      await new Promise((resolve) => setTimeout(resolve, 2000));

      // 提取基本信息 - 按照用户提供的CSS选择器
      const novelInfo = await page.evaluate(() => {
        // 1. 书名 - class="book-info" 中 id="bookName"
        const bookInfo = document.querySelector('.book-info');
        const bookNameElement = bookInfo?.querySelector('#bookName');
        const title = bookNameElement?.textContent?.trim() || '';

        // 2. 作者 - class="author" 去掉"作者:"前缀
        const authorElement = bookInfo?.querySelector('.author');
        let author = '';
        if (authorElement) {
          const authorText = authorElement.textContent?.trim() || '';
          author = authorText.replace(/^作者[:：]/, '').trim();
        }

        // 3. 状态 - class="book-attribute" 的第一个span
        const statusElement = bookInfo?.querySelector('.book-attribute span');
        const statusText = statusElement?.textContent?.trim() || '';

        // 4. 分类 - book-attribute 中的第一个a标签
        const categoryElement = bookInfo?.querySelector('.book-attribute a');
        const category = categoryElement?.textContent?.trim() || '';

        // 5. 字数 - class="count" 中第一个em
        const countElement = bookInfo?.querySelector('.count em');
        const wordCount = countElement?.textContent?.trim() || '';

        // 6. 简介 - class="intro-honor-label" 中 class="book-intro-detail"
        const introElement = document.querySelector(
          '.intro-honor-label .book-intro-detail',
        );
        const description = introElement?.textContent?.trim() || '';

        // 7. 标签 - class="all-label" 中 class="gray-hover" 可能有多个
        const tagElements = document.querySelectorAll('.all-label .gray-hover');
        const tags: string[] = [];
        tagElements.forEach((tag) => {
          const tagText = tag.textContent?.trim();
          if (tagText) {
            tags.push(tagText);
          }
        });

        // 8. 封面图片
        const coverElement = document.querySelector(
          '.book-info img, .book-cover img, .cover img',
        );
        const cover = coverElement?.getAttribute('src') || '';

        return {
          title,
          author,
          status: statusText,
          category,
          wordCount,
          description,
          tags,
          cover,
          updateTime: '', // 需要从其他地方获取
        };
      });

      // 提取章节列表
      const chapters = await this.extractChapterList(page);

      // 获取更新时间
      const updateTime = await this.getUpdateTime(page);

      const finalNovelInfo: NovelInfo = {
        title: novelInfo.title,
        author: novelInfo.author,
        cover: novelInfo.cover,
        description: novelInfo.description,
        category: novelInfo.category,
        wordCount: novelInfo.wordCount,
        status: this.parseStatus(novelInfo.status),
        updateTime: updateTime,
        chapterList: chapters,
      };

      return finalNovelInfo;
    } finally {
      await page.close();
    }
  }

  /**
   * 提取章节列表 - id="allCatalog" 中 class="chapter-item"
   */
  private async extractChapterList(
    page: puppeteer.Page,
  ): Promise<ChapterInfo[]> {
    try {
      // 等待目录加载
      await page.waitForSelector('#allCatalog', { timeout: 10000 });

      const chapters = await page.evaluate(() => {
        const chapterItems = document.querySelectorAll(
          '#allCatalog .chapter-item',
        );
        const chapters: ChapterInfo[] = [];

        chapterItems.forEach((item, index) => {
          // 章节名 - class="chapter-name"
          const chapterNameElement = item.querySelector('.chapter-name');
          const chapterTitle = chapterNameElement?.textContent?.trim() || '';

          // 章节链接 - chapter-name 是一个标签元素
          const chapterLink = chapterNameElement as HTMLAnchorElement;
          const chapterUrl = chapterLink?.href || '';

          // 判断是否收费 - 如果有 class="chapter-locked" 说明是收费的
          const isLocked = item.querySelector('.chapter-locked') !== null;
          const isFree = !isLocked; // 没有locked就是免费

          if (chapterTitle && chapterUrl) {
            chapters.push({
              title: chapterTitle,
              url: chapterUrl,
              index: index + 1,
              isFree: isFree,
              content: '', // 内容需要单独获取
              volumeName: '', // 可以从父级或其他地方获取卷名
            });
          }
        });

        return chapters;
      });

      return chapters;
    } catch (error) {
      console.error('提取章节列表失败:', error);
      return [];
    }
  }

  /**
   * 获取章节内容 - 章节页面中 class="chapter-wrapper" 内就是章节内容
   */
  async getChapterContent(chapterUrl: string): Promise<string> {
    if (!this.browser) {
      await this.initBrowser();
    }

    const page = await this.browser!.newPage();

    try {
      await page.setUserAgent(
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
      );

      await page.goto(chapterUrl, {
        waitUntil: 'networkidle2',
        timeout: 30000,
      });
      await new Promise((resolve) => setTimeout(resolve, 1000));

      // 等待章节内容加载
      await page.waitForSelector('.chapter-wrapper', { timeout: 10000 });

      const content = await page.evaluate(() => {
        const chapterWrapper = document.querySelector('.chapter-wrapper');
        if (chapterWrapper) {
          // 获取章节内容，可能需要清理一些HTML标签
          let content = chapterWrapper.textContent?.trim() || '';

          // 去除一些常见的无用文本
          content = content.replace(
            /^[\s\n]*[一二三四五六七八九十百千万]+、[\s\n]*/,
            '',
          ); // 去除章节标题
          content = content.replace(/[请记住本书首发域名.*?帮助宣传本书]/g, ''); // 去除推广信息
          content = content.replace(/[笔趣库.*?最新章节全文阅读]/g, ''); // 去除网站信息

          return content;
        }
        return '';
      });

      return content;
    } catch (error) {
      console.error('获取章节内容失败:', error);
      return '';
    } finally {
      await page.close();
    }
  }

  /**
   * 获取多个章节的详细内容
   */
  async getDetailedChapterList(
    url: string,
    maxChapters: number = 10,
  ): Promise<ChapterInfo[]> {
    const basicNovelInfo = await this.getNovelInfo(url);

    // 只获取前几个章节的内容以避免请求过多
    const chapters = basicNovelInfo.chapterList.slice(0, maxChapters);

    for (let i = 0; i < chapters.length; i++) {
      const chapter = chapters[i];
      if (chapter.isFree) {
        // 只获取免费章节的内容
        chapter.content = await this.getChapterContent(chapter.url);
      }

      // 添加延迟避免请求过快
      await new Promise((resolve) => setTimeout(resolve, 1000));
    }

    return chapters;
  }

  /**
   * 获取更新时间
   */
  private async getUpdateTime(page: puppeteer.Page): Promise<string> {
    try {
      const updateTime = await page.evaluate(() => {
        // 尝试多个可能的选择器
        const selectors = [
          '.book-info .update-time',
          '.book-info .time',
          '.update-info',
          '.book-info .last-update',
          '.book-info [class*="time"]',
          '.book-info [class*="update"]',
        ];

        for (const selector of selectors) {
          const element = document.querySelector(selector);
          if (element) {
            const text = element.textContent?.trim();
            if (text && text.length > 0) {
              return text;
            }
          }
        }

        return '';
      });

      return updateTime;
    } catch (error) {
      console.error('获取更新时间失败:', error);
      return '';
    }
  }

  /**
   * 解析小说状态
   */
  private parseStatus(statusText: string): number {
    if (statusText.includes('连载') || statusText.includes('连载中')) {
      return 1; // 连载中
    } else if (statusText.includes('完结') || statusText.includes('已完成')) {
      return 2; // 已完结
    } else if (statusText.includes('暂停') || statusText.includes('断更')) {
      return 3; // 暂停更新
    } else {
      return 1; // 默认连载中
    }
  }

  /**
   * 检查URL是否为起点域名
   */
  isSupportedUrl(url: string): boolean {
    return url.includes('qidian.com') || url.includes('yuewen.com');
  }
}
